package com.hospital.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hospital.domain.pojo.Reservation;
import com.hospital.domain.pojo.Schedule;
import com.hospital.domain.utils.Result;
import com.hospital.mapper.ReservationMapper;
import com.hospital.service.ReservationService;
import com.hospital.service.ScheduleService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;

@Service
@RequiredArgsConstructor
public class ReservationServiceImpl extends ServiceImpl<ReservationMapper, Reservation> implements ReservationService {
    private final ScheduleService scheduleService;

    @Transactional
    @Override
    public Result reservation(Integer pId, Integer dId, Integer depId, String date, String time, String info) {
        try {
            // 基础参数校验
            if (pId == null || dId == null || time == null || time.trim().isEmpty()) {
                return Result.fail("参数不完整，无法预约");
            }

            // 安全解析日期
            if (date == null || date.trim().isEmpty()) {
                return Result.fail("预约日期不能为空");
            }
            LocalDate localDate;
            try {
                localDate = LocalDate.parse(date.trim(), DateTimeFormatter.ISO_LOCAL_DATE);
            } catch (Exception e) {
                return Result.fail("预约日期格式不正确，应为YYYY-MM-DD");
            }

            // 标准化time
            time = time.trim();

            // 查询当天该医生该时段排班
            Schedule schedule = scheduleService.lambdaQuery()
                    .eq(Schedule::getDId, dId)
                    .eq(Schedule::getDate, localDate)
                    .eq(Schedule::getTime, time)
                    .one();
            if (schedule == null || schedule.getRemain() == null || schedule.getRemain() == 0) {
                return Result.fail("医生没排班或该时段已被约满");
            }

            // 生成唯一预约号: yyyymmdd + sId(3位) + 随机(4位)，最多重试5次避免唯一键冲突
            final String rNumDate = date.replace("-", "");
            final String rNumSId = String.format("%03d", schedule.getSId());
            String rNum = null;
            boolean uniqueFound = false;
            for (int i = 0; i < 5; i++) {
                String candidate = rNumDate + rNumSId + String.format("%04d", (int)(Math.random() * 10000));
                boolean exists = lambdaQuery().eq(Reservation::getRNum, candidate).one() != null;
                if (!exists) {
                    rNum = candidate;
                    uniqueFound = true;
                    break;
                }
            }
            if (!uniqueFound) {
                return Result.fail("系统繁忙，请稍后重试");
            }

            // 新增预约（补全创建时间，避免数据库非空约束）
            if (info == null) info = "";
            Integer sId = schedule.getSId();
            if (sId == null) {
                return Result.fail("排班数据异常：缺少sId");
            }
            Reservation reservation = new Reservation(pId, sId, rNum, 0, info);
            reservation.setRTime(java.time.LocalDateTime.now());
            boolean saved = save(reservation);
            if (!saved) {
                return Result.fail("预约保存失败");
            }

            // 更新余号/已预约
            boolean updated = scheduleService.lambdaUpdate()
                    .setSql("remain = remain - 1, already = already + 1")
                    .eq(Schedule::getDId, dId)
                    .eq(Schedule::getDate, localDate)
                    .eq(Schedule::getTime, time)
                    .update();
            if (!updated) {
                return Result.fail("更新排班失败");
            }

            return Result.ok("预约成功");
        } catch (Exception e) {
            return Result.fail("预约失败：" + e.getMessage());
        }
    }

    @Override
    public Result deleteReservation(Integer rId) {
        if(rId == null){
            return Result.fail("取消失败，请联系管理员");
        }
        Reservation reservation = lambdaQuery().eq(Reservation::getRId, rId).one();
        if(reservation.getRState() == 1){
            return Result.fail("已就诊");
        }
        else if(reservation.getRState() == 2){
            return Result.fail("已取消");
        }
        lambdaUpdate().setSql("rState = 2").eq(Reservation::getRId, rId).update();
        return Result.ok("取消成功");
    }

    @Override
    public Result queryAllReservations() {
        List<Map<String, Object>> reservations = baseMapper.queryAllReservationsWithInfo();
        return Result.ok(reservations);
    }
}
